/*
 * Copyright (c) 2011-2020 yanggq.young@allwinnertech.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 */
#ifndef __AW_PM_H__
#define __AW_PM_H__

#include "axp_depend.h"
#include <linux/types.h>
#include "../../../drivers/soc/allwinner/pm/pm.h"

#define BITMAP(bit) (0x1<<bit)

/**max device number of pmu*/
#define PMU_MAX_DEVS        2

/**
*@name PMU command
*@{
*/
#define AW_PMU_SET          0x10
#define AW_PMU_VALID        0x20
/**
*@}
*/

/*
* the wakeup source of main cpu: cpu0
*/
/* external interrupt, pmu event for ex.    */
#define CPU0_WAKEUP_MSGBOX      (1<<0)
/* key event    */
#define CPU0_WAKEUP_KEY         (1<<1)
#define CPU0_WAKEUP_EXINT	(1<<2)
#define CPU0_WAKEUP_IR		(1<<3)
#define CPU0_WAKEUP_ALARM	(1<<4)
#define CPU0_WAKEUP_USB		(1<<5)
#define CPU0_WAKEUP_TIMEOUT	(1<<6)
#define CPU0_WAKEUP_GPIO	(1<<7)

/* the wakeup source of assistant cpu: cpus */
#define CPUS_WAKEUP_LOWBATT     (1<<12)
#define CPUS_WAKEUP_USB         (1<<13)
#define CPUS_WAKEUP_AC          (1<<14)
#define CPUS_WAKEUP_ASCEND      (1<<15)
#define CPUS_WAKEUP_DESCEND     (1<<16)
#define CPUS_WAKEUP_SHORT_KEY   (1<<17)
#define CPUS_WAKEUP_LONG_KEY    (1<<18)
#define CPUS_WAKEUP_IR          (1<<19)
#define CPUS_WAKEUP_ALM0        (1<<20)
#define CPUS_WAKEUP_ALM1        (1<<21)
#define CPUS_WAKEUP_TIMEOUT     (1<<22)
#define CPUS_WAKEUP_GPIO        (1<<23)
#define CPUS_WAKEUP_USBMOUSE    (1<<24)
#define CPUS_WAKEUP_LRADC       (1<<25)
#define CPUS_WAKEUP_WLAN        (1<<26)
#define CPUS_WAKEUP_CODEC       (1<<27)
#define CPUS_WAKEUP_BAT_TEMP    (1<<28)
#define CPUS_WAKEUP_FULLBATT    (1<<29)
#define CPUS_WAKEUP_HMIC        (1<<30)
#define CPUS_WAKEUP_POWER_EXP   (1<<31)
#define CPUS_WAKEUP_KEY         (CPUS_WAKEUP_SHORT_KEY | CPUS_WAKEUP_LONG_KEY)

/* for format all the wakeup gpio into one word.*/
#define GPIO_PL_MAX_NUM		    (11)    /* 0-11 */
#define GPIO_PM_MAX_NUM		    (11)    /* 0-11 */
#define GPIO_AXP_MAX_NUM	    (7)	    /* 0-7 */

#define WAKEUP_GPIO_PL(num)         (1 << (num))
#define WAKEUP_GPIO_PM(num)         (1 << (num + 12))
#define WAKEUP_GPIO_AXP(num)        (1 << (num + 24))
#define WAKEUP_GPIO_GROUP(group)    (1 << (group - 'A'))

#if defined(CONFIG_ARCH_SUN8IW6P1) || defined(CONFIG_ARCH_SUN8IW8P1) \
	|| defined(CONFIG_ARCH_SUN50IW1P1) \
	|| defined(CONFIG_ARCH_SUN50IW2P1) \
	|| defined(CONFIG_ARCH_SUN8IW10P1) \
	|| defined(CONFIG_ARCH_SUN8IW11P1)
#define IO_NUM (2)
#elif defined(CONFIG_ARCH_SUN9IW1P1)
#define PLL_NUM (12)
#define BUS_NUM (15)
#define IO_NUM (2)
#else
#define IO_NUM (2)
#endif

#if defined(CONFIG_ARCH_SUN9IW1P1)
typedef struct {
	int n;
	int p;
	int divi; /* input_div */
	int divo; /* output_div */
} pll_para_t;
#elif defined(CONFIG_ARCH_SUN8IW6P1) || \
	defined(CONFIG_ARCH_SUN8IW8P1) || \
	defined(CONFIG_ARCH_SUN8IW10P1) || \
	defined(CONFIG_ARCH_SUN8IW11P1)  || \
	defined(CONFIG_ARCH_SUN50IW1P1) || \
	defined(CONFIG_ARCH_SUN50IW2P1)
typedef struct {
	unsigned int factor1;
	unsigned int factor2;
	unsigned int factor3;
	unsigned int factor4;
} pll_para_t;
#else
typedef struct {
	unsigned int n;	/* for a83, pll6, n*/
	unsigned int k;			/* div1 */
	unsigned int m;			/* div2 */
	unsigned int p;
} pll_para_t;
#endif

typedef struct {
	unsigned int src;
	unsigned int pre_div;
	unsigned int div_ratio;
	unsigned int n;
	unsigned int m;
} bus_para_t;

/* for bitmap macro definition */
#define PM_PLL_C0	(0)
#define PM_PLL_C1	(1)
#define PM_PLL_AUDIO	(2)
#define PM_PLL_VIDEO0	(3)
#define PM_PLL_VE	(4)
#define PM_PLL_DRAM	(5)
#define PM_PLL_PERIPH	(6)
#define PM_PLL_GPU	(7)
#define PM_PLL_HSIC	(8)
#define PM_PLL_DE	(9)
#define PM_PLL_VIDEO1	(10)
#define PLL_PERIPH1	(11)
#define PLL_DRAM1	(12)
#define PLL_MIPI	(13)
#define PLL_NUM		(14)

#define BUS_C0      (0)
#define BUS_C1      (1)
#define BUS_AXI0    (2)
#define BUS_AXI1    (3)
#define BUS_AHB1    (4)
#define BUS_AHB2    (5)
#define BUS_APB1    (6)
#define BUS_APB2    (7)
#define BUS_NUM	    (8)

#define OSC_HOSC_BIT	    (3)
#define OSC_LOSC_BIT	    (2)
#define OSC_LDO1_BIT	    (1)
#define OSC_LDO0_BIT	    (0)

typedef enum {
	CLK_SRC_NONE = 0x0, /* invalid source clock id */

	CLK_SRC_LOSC,   /* LOSC, 33/50/67:32768Hz, 73:16MHz/512=31250*/
	CLK_SRC_IOSC,   /* InternalOSC,  33/50/67:700KHZ, 73:16MHz*/
	CLK_SRC_HOSC,   /* HOSC, 24MHZ clock*/
	CLK_SRC_AXI,    /* AXI clock*/
	CLK_SRC_16M,    /* 16M for the backdoor*/

	CLK_SRC_PLL1,   /* PLL1 clock */
	CLK_SRC_PLL2,   /* PLL2 clock */
	CLK_SRC_PLL3,   /* PLL3 clock */
	CLK_SRC_PLL4,   /* PLL4 clock */
	CLK_SRC_PLL5,   /* PLL5 clock */
	CLK_SRC_PLL6,   /* PLL6 clock */
	CLK_SRC_PLL7,   /* PLL7 clock */
	CLK_SRC_PLL8,   /* PLL8 clock */
	CLK_SRC_PLL9,   /* PLL9 clock */
	CLK_SRC_PLL10,  /* PLL10 clock */
	CLK_SRC_PLL11,  /* PLL10 clock */

	CLK_SRC_CPUS,   /* cpus clock */
	CLK_SRC_C0,     /* cluster0 clock */
	CLK_SRC_C1,     /* cluster1 clock */
	CLK_SRC_AXI0,   /* AXI0 clock */
	CLK_SRC_AXI1,   /* AXI0 clock */
	CLK_SRC_AHB0,   /* AHB0 clock */
	CLK_SRC_AHB1,   /* AHB1 clock */
	CLK_SRC_AHB2,   /* AHB2 clock */
	CLK_SRC_APB0,   /* APB0 clock */
	CLK_SRC_APB1,   /* APB1 clock */
	CLK_SRC_APB2,   /* APB2 clock */
} clk_src_e;

typedef struct {
	/*
	 * for state bitmap:
	 * bitx = 1: keep state.
	 * bitx = 0: mean close corresponding power src.
   */
	unsigned int state;
	/* bitx=1, the corresponding state is effect,
	 * otherwise, the corresponding power is in charge in device driver.
	 *	sys_mask&state		: bitx=1,
	 *			mean the power is on,
	 *			for the "on" state power,
	 *			u need care about the voltage.;
	 *  ((~sys_mask)|state)	: bitx=0, mean the power is close;
	 *
	 * pwr_dm_state bitmap
	 * actually: we care about the pwr_dm voltage,
	 *   such as: we want to keep the vdd_sys at 1.0v at standby period.
	 * we actually do not care how to do it.
	 * it can be sure that cpus can do it with the pmu's help.
   */
	unsigned int sys_mask;
	unsigned int volt[VCC_MAX_INDEX]; /* unsigned short is 16bit width. */
} pwr_dm_state_t;

/* selfresh_flag must be compatible with vdd_sys pwr state.*/
typedef struct pm_dram_para {
	unsigned int selfresh_flag;
	unsigned int crc_en;
	unsigned int crc_start;
	unsigned int crc_len;
} pm_dram_para_t;

typedef struct cpus_clk_para {
    unsigned int cpus_id;
} cpus_para_t;

typedef struct io_state_config {
    unsigned int paddr;
    unsigned int value_mask; /* specify the effect bit.*/
    unsigned int value;
} io_state_config_t;

typedef struct soc_io_para {
    /*
     *	hold: mean before power off vdd_sys, whether hold gpio pad or not.
     *	this flag only effect: when vdd_sys is powered_off;
     *	this flag only affect hold&unhold operation.
     *	the recommended hold sequence is as follow:
     *	backup_io_cfg -> cfg_io(enter_low_power_mode)
     *  -> hold -> assert vdd_sys_reset -> poweroff vdd_sys.
     *  the recommended unhold sequence is as follow:
     *  poweron vdd_sys -> de_assert vdd_sys -> restore_io_cfg -> unhold.
     * */
    unsigned int hold_flag;


    /*
     * note: only specific bit mark by value_mask is effect.
     * IO_NUM: only uart and jtag needed care.
     * */
    io_state_config_t io_state[IO_NUM];
} soc_io_para_t;

typedef struct cpux_clk_para {
    /*
     * Hosc: losc: ldo1: ldo0
     * the osc bit map is as follow:
     * bit3: bit2: bit1:bit0
     * Hosc: losc: ldo1: ldo0
     */
    int osc_en;

    /*
     * for a83, pll bitmap as follow:
     *
     * pll11(video1):	pll10(de):  pll9(hsic)
     * bit7:	    bit6:	bit5:	    bit4:
     * pll8(gpu): pll6(periph): pll5(dram): pll4(ve):
     * bit3:		bit2:		bit1:	    bit0
     * pll3(video):	pll2(audio):	c1cpux:	    c0cpux
     *
     *
     *
     * */

    /* for disable bitmap:
     * bitx = 0: close
     * bitx = 1: do not care.
     */
    int init_pll_dis;

    /* for enable bitmap:
     * bitx = 0: do not care.
     * bitx = 1: open
     */
    int exit_pll_en;

    /*
     * set corresponding bit if it's pll factors need to be set some value.
     */
    int pll_change;

    /*
     * fill in the enabled pll freq factor sequently.
     * unit is khz pll6: 0x90041811
     * factor n/m/k/p already do the pretreatment of the minus one
     */
    pll_para_t pll_factor[PLL_NUM];

    /*
     * **********A31************
     * at a31 platform, the clk relationship is as follow:
     * pll1->cpu -> axi
     *	     -> atb/apb
     * ahb1 -> apb1
     * apb2
     * so, at a31, only cpu:ahb1:apb2 need be cared.
     *
     * *********A80************
     * at a83 platform, the clk relationship is as follow:
     * c1 -> axi1
     * c0 -> axi0
     * gtbus
     * ahb0
     * ahb1
     * ahb2
     * apb0
     * apb1
     * so, at a80, c1:c0:gtbus:ahb0:ahb1:ahb2:apb0:apb1 need be cared.
     *
     * *********A83************
     * at a83 platform, the clk relationship is as follow:
     * c1 -> axi1
     * c0 -> axi0
     * ahb1 -> apb1
     * apb2
     * ahb2
     * so, at a83, only c1:c0:ahb1:apb2:ahb2 need be cared.
     *
     * normally, only clk src need be cared.
     * the bus bitmap as follow:
     * for a83, bus_en:
     * bit4: bit3: bit2: bit1: bit0
     * ahb2: apb2: ahb1: c1:   c0
     *
     * for a31, bus_en:
     * bit2:bit1:bit0
     * cpu:ahb1:apb2
     *
     * for a80, bus_en:
     * bit7: bit6:  bit5:  bit4: bit3: bit2: bit1: bit0
     * c1:   c0:    gtbus: ahb0: ahb1: ahb2: apb0: apb1
     */
    int bus_change;

    /*
     * bus_src: ahb1, apb2 src;
     * option:  pllx:axi:hosc:losc
     */
    bus_para_t bus_factor[BUS_NUM];

} cpux_clk_para_t;

typedef struct soc_pwr_dep {
    /*
     * id of scene_lock
     */
    unsigned int id;

    pwr_dm_state_t soc_pwr_dm_state;
    pm_dram_para_t soc_dram_state;
    soc_io_para_t soc_io_state;
    cpux_clk_para_t cpux_clk_state;

} soc_pwr_dep_t;

typedef struct extended_standby {
	/*
	 * id of extended standby
	 */
	unsigned int id;
	unsigned int pmu_id;
	/* for: 808 || 809+806 || 803 || 813
	 * support 4 pmu: each pmu_id range is: 0-255;
	 * pmu_id <--> pmu_name have directly mapping,
	 * u can get the pmu_name from sys_config.fex files.;
	 * bitmap as follow:
	 * pmu0: 0-7 bit; pmu1: 8-15 bit; pmu2: 16-23 bit; pmu3: 24-31 bit
	 */


	unsigned int soc_id;
	/* a33, a80, a83,...,
	 * for compatible reason, different soc,
	 * each bit have different meaning.
	 */

	pwr_dm_state_t soc_pwr_dm_state;
	pm_dram_para_t soc_dram_state;
	soc_io_para_t soc_io_state;
	cpux_clk_para_t cpux_clk_state;
} extended_standby_t;


#define CPUS_ENABLE_POWER_EXP   (1<<31)
#define CPUS_WAKEUP_POWER_STA   (1<<1)
#define CPUS_WAKEUP_POWER_CSM   (1<<0)
typedef struct sst_power_info_para {
	/*
	 * define for sun9iw1p1
	 * power_reg bit0 ~ 7 AXP_main REG10, bit 8~15 AXP_main REG12
	 * power_reg bit16~23 AXP_slav REG10, bit24~31 AXP_slav REG11
	 *
	 * AXP_main REG10: 0-off, 1-on
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * aldo2  aldo1  dcdc5  dcdc4  dcdc3  dcdc2  dcdc1  dc5ldo
	 *
	 * REG12:
	 * bit0~5:0-off, 1-on,
	 * bit6~7: 0-on, 1-off, dc1sw's power come from dcdc1
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * dc1sw  swout  aldo3  dldo2  dldo1  eldo3  eldo2  eldo1
	 *
	 * AXP_slave REG10: 0-off, 1-on. dcdc b&c is not used, ignore them.
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * aldo3  aldo2  aldo1  dcdce  dcdcd  dcdcc  dcdcb  dcdca
	 *
	 * AXP_slave REG11: 0-off, 1-on
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * swout  cldo3  cldo2  cldo1  bldo4  bldo3  bldo2  bldo1
	 */
	/*
	 * define for sun8iw5p1
	 * power_reg0 ~ 7 AXP_main REG10,  8~15 AXP_main REG12
	 * power_reg16~32 null
	 *
	 * AXP_main REG10: 0-off, 1-on
	 * bit7   bit6	 bit5   bit4   bit3   bit2   bit1   bit0
	 * aldo2  aldo1  dcdc5  dcdc4  dcdc3  dcdc2  dcdc1  dc5ldo
	 *
	 * REG12: 0-off, 1-on
	 * bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0
	 * dc1sw  dldo4  dldo3  dldo2  dldo1  eldo3  eldo2  eldo1
	 *
	 * REG13: bit16 aldo3, 0-off, 1-on
	 * REG90: bit17 gpio0/ldo, 0-off, 1-on
	 * REG92: bit18 gpio1/ldo, 0-off, 1-on
	 */
	/* enable bit */
	/* registers of power state should be */
	/* the max power of system, signed, power mabe negative when charge */
	unsigned int enable;
	unsigned int power_reg;
	signed int system_power;
} sst_power_info_para_t;

/* cpus wakeup event types */
/* cpux resume code src */
/* cpux resume code length */
/* cpux resume entry */
/* wakeup after timeout seconds */
typedef	struct super_standby_para {
	unsigned int event;
	unsigned int resume_code_src;
	unsigned int resume_code_length;
	unsigned int resume_entry;
	unsigned int timeout;
	unsigned int gpio_enable_bitmap;
	unsigned int cpux_gpiog_bitmap;
	unsigned int pextended_standby;
} super_standby_para_t;

/* cpus wakeup event types */
/* wakeup after timeout seconds */
typedef	struct normal_standby_para {
	unsigned int event;
	unsigned int timeout;
	unsigned int gpio_enable_bitmap;
	unsigned int cpux_gpiog_bitmap;
	unsigned int pextended_standby;
} normal_standby_para_t;


/* define cpus wakeup src */
#define CPUS_MEM_WAKEUP              (CPUS_WAKEUP_LOWBATT |\
					CPUS_WAKEUP_USB |\
					CPUS_WAKEUP_AC |\
					CPUS_WAKEUP_DESCEND |\
					CPUS_WAKEUP_ASCEND |\
					CPUS_WAKEUP_ALM0 |\
					CPUS_WAKEUP_GPIO |\
					CPUS_WAKEUP_IR)

#define CPUS_BOOTFAST_WAKEUP         (CPUS_WAKEUP_LOWBATT |\
					CPUS_WAKEUP_LONG_KEY |\
					CPUS_WAKEUP_ALM0 |\
					CPUS_WAKEUP_USB |\
					CPUS_WAKEUP_AC)

/*used in normal standby*/
#define CPU0_MEM_WAKEUP              (CPU0_WAKEUP_MSGBOX |\
					CPU0_WAKEUP_EXINT |\
					CPU0_WAKEUP_ALARM)
#define CPU0_BOOTFAST_WAKEUP         (CPU0_WAKEUP_MSGBOX)


/**
*@brief struct of pmu device arg
*/
struct aw_pmu_arg {
    unsigned int  twi_port;		/**<twi port for pmu chip   */
    unsigned char dev_addr;		/**<address of pmu device   */
    unsigned int soc_power_tree[VCC_MAX_INDEX];  /* power tree struct point */
};


/**
 *@brief struct of standby
 *event: <event type for system wakeup
 *axp_event: <axp event type for system wakeup
 *debug_mask: debug mask
 *timeout: <time to power off system from now, based on second
 */
struct aw_standby_para {
	unsigned int event;
	unsigned int axp_event;
	unsigned int debug_mask;
	signed int   timeout;
	unsigned int gpio_enable_bitmap;
	unsigned int cpux_gpiog_bitmap;
	unsigned int pextended_standby;
};

/**
*@brief struct of power management info
*/
struct aw_pm_info {
    /* standby parameter            */
    struct aw_standby_para		standby_para;
    /**<args used by main function  */
    struct aw_pmu_arg			pmu_arg;
#if defined(CONFIG_ARCH_SUN8IW10P1) || defined(CONFIG_ARCH_SUN8IW11P1)
    dram_para_t                         dram_para;
    unsigned long                       resume_addr;
#endif
};

typedef struct sst_dram_info {
	unsigned int dram_crc_enable;
	unsigned int dram_crc_src;
	unsigned int dram_crc_len;
	unsigned int dram_crc_error;
	unsigned int dram_crc_total_count;
	unsigned int dram_crc_error_count;
} sst_dram_info_t;

typedef struct standby_info_para {
	sst_power_info_para_t power_state; /* size 3W=12B */
	sst_dram_info_t dram_state; /*size 6W=24B */
} standby_info_para_t;

typedef enum event_cpu_id {
    CPUS_ID,
    CPU0_ID,
} event_cpu_id_e;

typedef struct standby_space_cfg {
    struct device_node *np;
    phys_addr_t standby_mem_base;
    phys_addr_t extended_standby_mem_base;
    phys_addr_t mem_offset;
    size_t mem_size;
} standby_space_cfg_t;

extern unsigned int parse_wakeup_gpio_group_map(char *s, unsigned int size,
					unsigned int gpio_map);

extern unsigned int parse_wakeup_event(char *s, unsigned int size,
				unsigned int event);

extern unsigned int parse_wakeup_gpio_map(char *s, unsigned int size,
				unsigned int gpio_map);

extern unsigned int show_gpio_config(char *s, unsigned int size);

#endif /* __AW_PM_H__ */
